package com.test.platform.service.common;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.platform.config.TokenConfig;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.io.IOException;

@Service
public class GitCodeApiClient {
    private static final Logger logger = LoggerFactory.getLogger(GitCodeApiClient.class);
    private final OkHttpClient client = new OkHttpClient();
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private TokenConfig tokenConfig;

    @Value("${gitcode.client.secret}")
    private String clientSecret;

    @Autowired
    private RepoConfigService repoConfigService;

    // 添加新方法检查仓库是否存在
    private boolean checkRepoExists(String owner, String name) {
        try {
            String url = String.format("https://api.gitcode.com/api/v5/repos/%s/%s?access_token=%s",
                    owner, name, tokenConfig.getGitcodeAccessToken());
            
            Request request = new Request.Builder()
                    .url(url)
                    .build();

            try (Response response = client.newCall(request).execute()) {
                return response.isSuccessful();
            }
        } catch (Exception e) {
            logger.error("检查仓库状态时发生错误: {}/{}", owner, name, e);
            return false;
        }
    }
    
    public JsonNode fetchLatestPR(String owner, String name) {
        try {
            String url = null;
            if ("openharmony_tpc_samples".equals(name)) {
                Map<String, Map<String, String>> prInfo = matchPRsWithSamples(owner, name);
                return !prInfo.isEmpty() ? objectMapper.valueToTree(prInfo) : null;
            } else if ("openharmony-sig".equals(owner) || "openharmony-tpc".equals(owner)) {
                // 先检查仓库是否存在
                if (!checkRepoExists(owner, name)) {
                    logger.warn("仓库不存在或无访问权限: {}/{}", owner, name);
                    return null;
                }
                url = String.format("https://api.gitcode.com/api/v5/repos/%s/%s/pulls?access_token=%s&page=1&per_page=1",
                        owner, name, tokenConfig.getGitcodeAccessToken());
            } else {
                logger.warn("不支持的仓库所有者: {}", owner);
                return null;
            }
            
            if (url == null) {
                return null;
            }
            
            Request request = new Request.Builder()
                    .url(url)
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    logger.error("获取PR信息失败: {}/{}, 状态码: {}", owner, name, response.code());
                    return null;
                }
                String responseBody = response.body().string();
                JsonNode prInfo = objectMapper.readTree(responseBody);
                
                // 处理 PR 信息
                if (prInfo.isArray() && prInfo.size() > 0) {
                    JsonNode pr = prInfo.get(0);
                    String number = pr.path("number").asText();
                    String developer = pr.path("user").path("name").asText();
                    String title = pr.path("title").asText();
                    String sha = pr.path("head").path("sha").asText();
                    // 将sha添加到返回结果中
                    ((ObjectNode) pr).put("commit_sha", sha);
                    logger.info("成功获取PR信息: 编号={}, 开发者={}, 标题={}, SHA={}", 
                            number, developer, title, sha);
                }
                
                return prInfo;
            }
        } catch (Exception e) {
            logger.error("获取PR信息时发生错误: {}/{}", owner, name, e);
            return null;
        }
    }

    // 新增方法：获取 PR 总数
    private int fetchPRTotalCount(String owner, String name) {
        try {
            String encodedRepo = String.format("%s%%2F%s", owner, name);
            String url = String.format("https://web-api.gitcode.com/issuepr/api/v1/projects/%s/isource/merge_requests?scope=all&state=merged&page=1&repoId=%s&per_page=50&view=basic",
                    encodedRepo, encodedRepo.replace("%2F", "%252F"));
            
            Request request = new Request.Builder()
                    .url(url)
                    .header("Accept", "application/json, text/plain, */*")
                    .header("Accept-Language", "zh-CN,zh;q=0.9")
                    .header("Authorization", "Bearer " + clientSecret)
                    .header("Origin", "https://gitcode.com")
                    .header("Referer", "https://gitcode.com/")
                    .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36")
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    logger.error("获取PR总数失败: {}, 状态码: {}", url, response.code());
                    throw new IOException("获取PR总数失败: " + response.code());
                }
                String responseBody = response.body().string();
                int total = objectMapper.readTree(responseBody).get("total").asInt(0);
                logger.info("获取到PR总数: {}/{} = {}", owner, name, total);
                return total;
            }
        } catch (Exception e) {
            logger.error("获取PR总数时发生错误: {}/{}", owner, name, e);
            return 0;
        }
    }

    public void updateAllRepos() {
        try {
            List<Map<String, String>> repos = repoConfigService.loadRepoConfigs();
            logger.info("开始更新所有仓库信息，共 {} 个仓库", repos.size());

            for (Map<String, String> repo : repos) {
                String owner = repo.get("owner");
                String name = repo.get("name");
                updateLatestPR(owner, name);
            }
            logger.info("所有仓库信息更新完成");
        } catch (Exception e) {
            logger.error("批量更新仓库信息时发生错误", e);
            throw new RuntimeException("更新仓库信息失败", e);
        }
    }

    public void updateLatestPR(String owner, String name) {
        try {
            JsonNode prInfo = fetchLatestPR(owner, name);
            if (prInfo != null) {
                logger.info("成功更新仓库PR信息: {}/{}", owner, name);
            } else {
                logger.warn("未获取到PR信息: {}/{}", owner, name);
            }
        } catch (Exception e) {
            logger.error("更新PR信息时发生错误: {}/{}", owner, name, e);
            throw new RuntimeException("更新PR信息失败: " + e.getMessage(), e);
        }
    }

    public JsonNode fetchPRChanges(String owner, String name, String prNumber) {
        try {
            String encodedRepo = String.format("%s%%2F%s", owner, name);
            String url = String.format("https://web-api.gitcode.com/issuepr/api/v1/projects/%s/merge_requests/%s/changes_trees?repoId=%s&iid=%s&view=simple",
                    encodedRepo, prNumber, encodedRepo.replace("%2F", "%252F"), prNumber);
            
            Request request = new Request.Builder()
                    .url(url)
                    .header("Accept", "application/json, text/plain, */*")
                    .header("Authorization", "Bearer " + clientSecret)
                    .header("Origin", "https://gitcode.com")
                    .header("Referer", "https://gitcode.com/")
                    .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36")
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) {
                    logger.error("获取PR变更信息失败: {}, PR号: {}, 状态码: {}", name, prNumber, response.code());
                    return null;
                }
                return objectMapper.readTree(response.body().string());
            }
        } catch (Exception e) {
            logger.error("获取PR变更信息时发生错误: {}, PR号: {}", name, prNumber, e);
            return null;
        }
    }

    public Map<String, Map<String, String>> matchPRsWithSamples(String owner, String name) {
        Map<String, Map<String, String>> prInfo = new HashMap<>();
        Map<String, String> sampleToPR = new HashMap<>();  // 记录样例名称到PR号的映射
        try {
            // 读取本地的 repos_sample.json
            JsonNode sampleConfig = loadReposSampleConfig();
            if (sampleConfig == null) {
                logger.error("无法加载 repos_sample.json 配置");
                return prInfo;
            }
            Set<String> sampleNames = new HashSet<>();
            for (JsonNode sample : sampleConfig) {
                sampleNames.add(sample.path("name").asText());
            }

            int total = fetchPRTotalCount(owner, name);
            int totalPages = (total + 99) / 100;  // 使用100条每页
            
            for (int page = 1; page <= totalPages; page++) {
                String encodedRepo = String.format("%s%%2F%s", owner, name);
                String url = String.format("https://web-api.gitcode.com/issuepr/api/v1/projects/%s/isource/merge_requests?scope=all&state=merged&page=%d&repoId=%s&per_page=100&view=basic",
                        encodedRepo, page, encodedRepo.replace("%2F", "%252F"));
                
                Request request = new Request.Builder()
                        .url(url)
                        .header("Accept", "application/json, text/plain, */*")
                        .header("Authorization", "Bearer " + clientSecret)
                        .header("Origin", "https://gitcode.com")
                        .header("Referer", "https://gitcode.com/")
                        .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36")
                        .build();

                try (Response response = client.newCall(request).execute()) {
                    if (!response.isSuccessful()) continue;
                    
                    JsonNode prs = objectMapper.readTree(response.body().string()).get("records");
                    if (prs != null && prs.isArray()) {
                        for (JsonNode pr : prs) {
                            String prNumber = pr.path("iid").asText();
                            JsonNode changes = fetchPRChanges(owner, name, prNumber);
                            if (changes != null) {
                                String sha = pr.path("head").path("sha").asText();
                                Map<String, String> details = new HashMap<>();
                                details.put("sha", sha);
                                processChangesTree(changes, prNumber, sampleNames, details);
                                
                                // 如果找到了匹配的样例
                                if (details.containsKey("title")) {
                                    String sampleName = details.get("title");
                                    // 如果这个样例还没有对应的PR，或者这是第一页（最新的PR）
                                    if (!sampleToPR.containsKey(sampleName) || page == 1) {
                                        prInfo.put(prNumber, details);
                                        sampleToPR.put(sampleName, prNumber);
                                        logger.info("更新PR和样例匹配: PR#{} -> {} (SHA: {})", 
                                                prNumber, sampleName, sha);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("匹配PR和样例时发生错误", e);
        }
        return prInfo;
    }

    private JsonNode loadReposSampleConfig() {
        try {
            // 修正路径拼接，添加分隔符
            String configPath = System.getProperty("user.dir") + "/backend/src/main/resources/data/repos_sample.json";
            // 将路径中的正斜杠替换为系统相关的分隔符
            configPath = configPath.replace("/", File.separator);
            logger.info("尝试加载配置文件: {}", configPath);
            File configFile = new File(configPath);
            
            if (!configFile.exists()) {
                logger.error("配置文件不存在: {}", configPath);
                // 确保目录存在
                File parentDir = configFile.getParentFile();
                if (!parentDir.exists()) {
                    boolean created = parentDir.mkdirs();
                    logger.info("创建目录 {}: {}", parentDir.getAbsolutePath(), created ? "成功" : "失败");
                }
                return null;
            }
            
            return objectMapper.readTree(configFile);
        } catch (Exception e) {
            logger.error("读取 repos_sample.json 配置文件失败: {}", e.getMessage());
            return null;
        }
    }

    private void processChangesTree(JsonNode changes, String prNumber, Set<String> sampleNames, Map<String, String> details) {
        JsonNode tree = changes.path("tree");
        if (tree.isArray()) {
            for (JsonNode item : tree) {
                String title = item.path("title").asText();
                if (sampleNames.contains(title)) {
                    details.put("title", title);
                    break;
                }
            }
        }
    }

    public Map<String, String> fetchChangelog(String owner, String name, String sampleName) {
            try {
                String content = null;
                Map<String, String> result = new HashMap<>();
                
                if (("openharmony-sig".equals(owner) || "openharmony-tpc".equals(owner)) 
                        && !"openharmony_tpc_samples".equals(name)) {
                    // 尝试不同的 changelog 路径
                    String[] paths = {
                        String.format("https://raw.gitcode.com/%s/%s/raw/master/CHANGELOG.md", owner, name),
                        String.format("https://raw.gitcode.com/%s/%s/raw/master/changelog.md", owner, name)
                    };
                    
                    // 特殊处理 openharmony-sig/ohos_webrtc
                    if ("openharmony-sig".equals(owner) && "ohos_webrtc".equals(name)) {
                        paths = new String[]{
                            "https://raw.gitcode.com/openharmony-sig/ohos_webrtc/raw/master/sdk/ohos/changelog.md"
                        };
                    }
                    
                    content = fetchChangelogContent(paths);
                } else if ("openharmony-tpc".equals(owner) && "openharmony_tpc_samples".equals(name)) {
                    String[] paths = {
                        String.format("https://raw.gitcode.com/openharmony-tpc/openharmony_tpc_samples/raw/master/%s/CHANGELOG.md", sampleName),
                        String.format("https://raw.gitcode.com/openharmony-tpc/openharmony_tpc_samples/raw/master/%s/changelog.md", sampleName)
                    };
                    content = fetchChangelogContent(paths);
                }
                
                if (content != null) {
                    parseChangelog(content, result);
                }
                
                return result;
            } catch (Exception e) {
                logger.error("获取变更日志时发生错误: {}/{}", owner, name, e);
                return new HashMap<>();
            }
        }

        private String fetchChangelogContent(String[] paths) {
            for (String url : paths) {
                try {
                    Request request = new Request.Builder()
                            .url(url)
                            .build();

                    try (Response response = client.newCall(request).execute()) {
                        if (response.isSuccessful()) {
                            return response.body().string();
                        }
                    }
                } catch (Exception e) {
                    logger.warn("尝试获取 changelog 失败: {}", url, e);
                }
            }
            return null;
        }

        private void parseChangelog(String content, Map<String, String> result) {
            String[] sections = content.split("##");
            if (sections.length > 1) {
                String latestSection = sections[1].trim();
                String[] lines = latestSection.split("\n", 2);
                if (lines.length > 1) {
                    String version = lines[0].trim();
                    String changelog = lines[1].trim();
                    
                    // 如果还有下一个##，截断到那里
                    int nextSection = changelog.indexOf("##");
                    if (nextSection != -1) {
                        changelog = changelog.substring(0, nextSection).trim();
                    }
                    
                    result.put("version", version);
                    result.put("changelog", changelog);
                    logger.info("成功解析 changelog: version={}, content={}", version, changelog);
                }
            }
        }
}